package com.onesports.intelligent.k12.polarlight.security.wx;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.onesports.intelligent.k12.polarlight.constant.SystemCodeConstants;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 微信小程序登录
 *
 * @author aj
 */
@Slf4j
public class WxAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private final WxMaService wxMaService;

    protected WxAuthenticationFilter(WxMaService wxMaService) {
        super(new AntPathRequestMatcher("/auth/wx/login", "POST"));
        this.wxMaService = wxMaService;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        if (!request.getMethod().equals(HttpMethod.POST.name())) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }
        String openid;
        WxLoginInfo wxLoginInfo;
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//        Map<String, String> authenticationBean = mapper.readValue(request.getInputStream(), Map.class);
        WxLoginDTO wxloginDTO = mapper.readValue(request.getInputStream(), WxLoginDTO.class);

        if (StringUtils.isBlank(wxloginDTO.getJsCode())) {
            throw new AuthenticationServiceException("jscode can not be null");
        }
        if (StringUtils.isBlank(wxloginDTO.getCode())) {
            throw new AuthenticationServiceException("code can not be null");
        }

        try {
            WxMaJscode2SessionResult session = this.wxMaService.getUserService().getSessionInfo(wxloginDTO.getJsCode());
            WxMaPhoneNumberInfo phoneNumberInfo = wxMaService.getUserService().getNewPhoneNoInfo(wxloginDTO.getCode());
            openid = session.getOpenid();

            wxLoginInfo = WxLoginInfo.builder()
                    .openId(openid)
                    .purePhoneNumber(phoneNumberInfo.getPurePhoneNumber())
                    .nickName(wxloginDTO.getNickname())
                    .avatarUrl(wxloginDTO.getAvatarUrl())
                    .systemCode(SystemCodeConstants.WX)
                    .build();
        } catch (WxErrorException e) {
            log.error(e.getMessage(), e);
            throw new AuthenticationServiceException("获取授权信息错误，请重新授权！");
        }
        WxAuthenticationToken authRequest = new WxAuthenticationToken(openid);
        authRequest.setDetails(wxLoginInfo);
        return this.getAuthenticationManager().authenticate(authRequest);
    }

}
